package cn.lycode.system.service.impl;

import cn.lycode.common.core.domain.entity.SysRole;
import cn.lycode.common.core.domain.entity.SysUser;
import cn.lycode.common.core.domain.model.ConditionDTO;
import cn.lycode.common.core.domain.model.SelectIdsDTO;
import cn.lycode.common.core.domain.model.user.RegisterBody;
import cn.lycode.common.core.page.PageResult;
import cn.lycode.common.core.page.PageUtil;
import cn.lycode.common.enums.ErrorEnum;
import cn.lycode.common.event.EventPublisher;
import cn.lycode.common.event.SessionChangeEvent;
import cn.lycode.common.event.SessionChangeMeta;
import cn.lycode.common.utils.SecurityUtils;
import cn.lycode.common.utils.StringUtils;
import cn.lycode.system.constant.ParamConstant;
import cn.lycode.system.domain.dto.sysmenu.SysUserRoleDTO;
import cn.lycode.system.domain.dto.sysuser.*;
import cn.lycode.system.domain.vo.SysUserRoleVO;
import cn.lycode.system.domain.vo.SysUserVO;
import cn.lycode.system.mapper.SysUserMapper;
import cn.lycode.system.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @Title: SysUserServiceImpl
 * @Author lyg
 * @Date 2024/6/28 17:31
 * @description: 用户实现类
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class SysUserServiceImpl implements SysUserService {

    private final SysRoleService sysRoleService;
    private final SysUserRoleService sysUserRoleService;
    private final SysUserPostService sysUserPostService;
    private final EventPublisher eventPublisher;


    private final SysUserMapper sysUserMapper;

    @Override
    public SysUser getSysUserByUsernameOrNo(String input) {
        SysUser user = sysUserMapper.selectUserByUsername(input);
        if (user == null) {
            user = sysUserMapper.selectUserByPersonNo(input);
        }
        return user;
    }

    @Override
    public SysUser getSysUserByUserId(Long userId) {
        return sysUserMapper.selectUserByUserId(userId);
    }

    /**
     * 检查用户名是否唯一
     * @param username 用户名
     * @return 唯一返回true，已存在返回false
     */
    @Override
    public boolean checkUsernameUnique(String username) {
        return sysUserMapper.countUsername(username) <= 0;
    }

    @Override
    public boolean checkUsernameUniqueExceptUserId(String username, Long userId) {
        return sysUserMapper.countUsernameExceptUserId(username, userId) <= 0;
    }

    /**
     * 根据用户id，查出所有角色及用户具备的角色
     * @param userId 用户id
     * @return 所有角色和用户具备的角色id
     */
    @Override
    public SysUserRoleVO findSysUserRole(Long userId) {
        List<SysRole> sysRoleList = sysRoleService.selectRoleAll();
        List<SysUserRoleVO.RoleInfoVO> roleInfoVOS = new ArrayList<>();
        for (SysRole sysRole : sysRoleList) {
            roleInfoVOS.add(new SysUserRoleVO.RoleInfoVO(sysRole.getId(), sysRole.getRoleName()));
        }

        SysUserRoleVO sysUserRoleVO = new SysUserRoleVO();
        sysUserRoleVO.setRoleInfoVOS(roleInfoVOS);
        List<Long> userRoleList = sysUserRoleService.selectUserRoleIds(userId);
        sysUserRoleVO.setSelectIds(userRoleList);
        return sysUserRoleVO;
    }

    @Override
    public void changeSysUserRole(SysUserRoleDTO dto) {
        // 删除当前用户下的所有角色
        sysUserRoleService.deleteUserAllRoles(dto.getUserId());
        // 插入用户的所有角色
        if (!StringUtils.isEmpty(dto.getRoleIds())) {
            sysUserRoleService.batchAddUserRoles(dto.getUserId(), dto.getRoleIds());
        }
//        //更新此用户的session里面的权限。
        eventPublisher.publish(new SessionChangeEvent(this, SessionChangeMeta.user(dto.getUserId())));
    }

    @Override
    public SysUserVO getUserInfo(Long userId) {
        return sysUserMapper.selectUserVOByUserId(userId);
    }

    @Override
    public boolean changePassword(SysUserPasswordDTO dto) {
        SysUser user = sysUserMapper.selectUserByUserId(SecurityUtils.getLoginUserId());
        //校验密码
        ErrorEnum.BAD_USERNAME_OR_PASSWORD.assertTrue(SecurityUtils.checkPassword(dto.getOldPwd(), user.getPassword()));
        //修改密码
        sysUserMapper.updateUserPwd(SecurityUtils.getLoginUserId(),SecurityUtils.sha256Encrypt(dto.getNewPwd()));
        SecurityUtils.clearLoginUserSession();
        return true;
    }

    @Override
    public boolean resetPassword(Long id) {
        sysUserMapper.updateUserPwd(id, SecurityUtils.sha256Encrypt(ParamConstant.sysUserInitPwd));
        return true;
    }



    @Override
    public void bindUserDept(UserDeptDTO dto) {
        //给用户批量设置部门
        sysUserMapper.updateUsersDept(dto.getUserIds(), dto.getDeptId());
    }

    @Override
    @Transactional
    public void bindUserPost(UserPostDTO dto) {
        //给用户批量设置岗位
        //1.删除用户具备的岗位关联
        sysUserPostService.deleteUserPostByUserIds(dto.getUserIds());
        //2.重新添加新的岗位关联
        sysUserPostService.batchAddUserPost(dto.getUserIds(), dto.getPostIds());
    }

    @Override
    public boolean registerUser(RegisterBody registerBody) {
        return false;
    }

    @Override
    public PageResult<SysUserVO> list(ConditionDTO dto) {
        PageUtil.startPage(dto);
        List<SysUserVO> sysUserVOS = new ArrayList<>();
        if (dto.getDeptId() != null && dto.getDeptId() == -1) {
            //-1 表示部门列表选择为：全部
            sysUserVOS = sysUserMapper.selectAllDeptUserVOList(dto);
        }else if (dto.getDeptId() != null && dto.getDeptId() == -2) {
            //-1 表示部门列表选择为：未设置部门
            sysUserVOS = sysUserMapper.selectNoDeptUserVOList(dto);
        }else if (dto.getIsThisDeep() != null && dto.getIsThisDeep()) {
            //查询指定部门的列表
            sysUserVOS = sysUserMapper.selectUserVOListByDept(dto);
        }else {
            sysUserVOS = sysUserMapper.selectUserVOListByDeptAndChildren(dto);
        }

        return PageUtil.getPageResult(sysUserVOS);
    }

    @Override
    public List<SysUser> allUserList() {
        return sysUserMapper.selectAllUserList();
    }

    @Override
    public int add(SysUserAddDTO dto) {
        ErrorEnum.EXIST_USERNAME.assertTrue(checkUsernameUnique(dto.getUsername()));
        SysUser user = new SysUser();
        BeanUtils.copyProperties(dto, user);
        String encodePwd = SecurityUtils.sha256Encrypt(ParamConstant.sysUserInitPwd);
        user.setPassword(encodePwd);
        user.setAccountStatusCd("1000001");  //默认正常状态
        user.setCreateTime(new Date());
        return sysUserMapper.insertUser(user);
    }

    @Override
    public SysUserVO detail(Long id) {
        return sysUserMapper.selectUserVOByUserId(id);
    }

    @Override
    @Transactional
    public int update(SysUserUpDTO dto) {
        //保证更新用户名和他人不重复
        ErrorEnum.EXIST_USERNAME.assertTrue(checkUsernameUniqueExceptUserId(dto.getUsername(), dto.getId()));
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(dto, sysUser);
        //更新用户基本信息
        int ret = sysUserMapper.updateUser(sysUser);
        //更新用户岗位信息
        bindUserPost(new UserPostDTO(Collections.singletonList(dto.getId()), dto.getPostIdList()));
        return ret;
    }

    @Override
    public int unlockUser(List<Long> ids) {
        // TODO 实现用户多次登录失败，账户锁定功能后， 完善解锁用户功能
        return ids.size();
    }


    @Override
    @Transactional
    public void remove(SelectIdsDTO dto) {
        ErrorEnum.INVALID_ID.assertFalse(dto.getIds().isEmpty());
        sysUserMapper.updateUserIsDelete(dto.getIds());
        // 解绑_用户-角色关系
        sysUserRoleService.deleteUserAllRolesByUserIds(dto.getIds());
    }


}
